#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// NeatlyFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Neatly.Load
{
    public abstract class Loader : ILoadObject
    {
        //加载结果
        public Object ResultObject {get; protected set;}
        private Dictionary<string, Object> m_AssetPool;
        private Dictionary<string, Object> AssetPool => m_AssetPool ??= new Dictionary<string, Object>();
        //是否错误(文件修复)
        public bool IsError {get; private set;}
        //是否同步
        public bool IsSync {get; private set;}

        public void Unload(bool unload)
        {
            var bundle = ResultObject as AssetBundle;
            if (bundle != null)
            {
                NeatlyConfig.AssetBundleUnloadAction(bundle, unload);
            }
        }

        public bool ContainAsset(string assetName)
        {
            return AssetPool.ContainsKey(assetName);
        }

        //引用数
        public int RefCount {get; set;}
        //依赖数
        public int DependCount {get; private set;}
        //路径,也是key
        public string Path {get; private set;}
        //是否常驻内存
        public bool Persistent {get; private set;}
        //存在时间
        public float LiveTime {get; set;}
        #region Atlas
        //是否图集bundle
        public bool IsAtlas {get; set;}
        public string AtlasName {get; set;}
        //图集名
        public NAtlas AtlasInfo {get; set;}
        #endregion

        //初始化
        protected virtual void Init(string path, bool sync = true)
        {
            Persistent = LoaderConfig.CheckPersistent(path);
            RefCount = 0;
            DependCount = 0;
            LiveTime = Time.realtimeSinceStartup;
            IsSync = sync;
            IsError = false;
            Path = path;
        }

        protected abstract UniTask<Loader> Load();

        public virtual void Update()
        {
        }

        protected void OnLoadCompleted(Object data)
        {
            ResultObject = data;
        }

        //添加引用计数
        public void AddReferenceCount()
        {
            RefCount++;
        }

        //移除引用计数
        public void LoseReferenceCount()
        {
            RefCount--;
            if (RefCount <= 0 && DependCount <= 0)
            {
                LiveTime = Time.realtimeSinceStartup;
            }
        }

        //添加依赖计数
        public void AddDependCount()
        {
            DependCount++;
        }

        //移除依赖计数
        public void LoseDependCount()
        {
            DependCount--;
            if (RefCount <= 0 && DependCount <= 0)
            {
                LiveTime = Time.realtimeSinceStartup;
            }
        }

        //设置是否常驻
        public void SetPersistent(bool isPersistent)
        {
            if (isPersistent)
            {
                Persistent = true;
            }
        }

        public static async UniTask<Loader> AutoLoad<T>(string path, bool sync = true) where T : Loader, new()
        {
            T t = new T();
            t.Init(path, sync);
            return await t.Load();
        }

        public T LoadAsset<T>(string name) where T : Object
        {
            //添加引用计数
            AddReferenceCount();
            if (AssetPool.TryGetValue(name, out var cacheAsset))
            {
                return cacheAsset as T;
            }
            var bundle = ResultObject as AssetBundle;
            Developer.StartLoadAsset(name);
            T asset = bundle.LoadAsset<T>(name);
            Developer.EndLoadAsset(name);
            AssetPool.Add(name, asset);
            return asset;
        }
    }
}